package com.karolak.math.view;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.DynamicTimeSeriesCollection;
import org.jfree.data.time.Second;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;

import com.karolak.math.MathUtils;
import com.karolak.stock.data.DataManager;
import com.karolak.stock.strategy.Strategy;
import com.karolak.stock.strategy.SwStrategy;

public class ChartInd extends ApplicationFrame {

	private static final long serialVersionUID = 1L;

	private DataManager dataManager;
	private ChartManager chartManager;

	private int historySize;
	private int chartSize;

	private Map<String, DynamicTimeSeriesCollection> datasets;

	public ChartInd(String title) {
		super(title);
		init();
	}

	protected void init() {
		this.datasets = new LinkedHashMap<String, DynamicTimeSeriesCollection>();

		setChartManager(new ChartManager(this));

		Strategy strategy = new SwStrategy();

		setDataManager(strategy.getDataManager());
		setHistorySize(strategy.getConfig().getHistorySize());
		setChartSize(strategy.getConfig().getChartSize());

		createDataSets();
		createCharts();

		setSize(getWidth(), 200);
	}

	// === public apid === //
	public void execute(double x) {
		getDataManager().update(x);
		updateDataSets();
	}

	public void updateDataSets() {
		for (String chartName : getDatasets().keySet()) {
			DynamicTimeSeriesCollection dataset = getDatasets().get(chartName);
			dataset.advanceTime();
			int ix = dataset.getNewestIndex();
			List<String> seriesList = getDataManager().getChartSeries().get(chartName);

			for (int i = 0; i < seriesList.size(); i++) {
				String seriesName = seriesList.get(i);
				double last = getDataManager().getLast(seriesName);
				dataset.addValue(i, ix, (float) last);
			}
		}
	}

	protected void createDataSets() {

		// === create data sets === //
		for (String chartName : getDataManager().getChartSeries().keySet()) {
			List<String> series = getDataManager().getChartSeries().get(chartName);
			if (series == null || series.isEmpty()) {
				continue;
			}
			DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(series.size(), getChartSize(), new Second());

			// dataset.setTimeBase(new Second(0, 0, 0, 1, 1, 2011));
			dataset.setTimeBase(new Second(27, 13, 21, 6, 12, 2009));

			// === init static chart === //
			for (int i = 0; i < series.size(); i++) {
				String seriesName = series.get(i);
				float[] values = MathUtils.toFloat(getDataManager().getSeries(seriesName, getChartSize()));
				dataset.addSeries(values, i, seriesName);
				// dataset.addSeries(init, i, seriesName);
			}
			getDatasets().put(chartName, dataset);
		}
	}

	protected void createCharts() {
		JPanel panel = new JPanel(new GridLayout(getDatasets().size(), 1));
		for (String chartName : getDatasets().keySet()) {
			JFreeChart chart = createChart(chartName, getDatasets().get(chartName));
			panel.add(new ChartPanel(chart));
		}
		this.add(panel, BorderLayout.CENTER);
	}

	protected JFreeChart createChart(String chartName, final XYDataset dataset) {
		JFreeChart result = ChartFactory.createTimeSeriesChart(chartName, "hh:mm:ss", "Y", dataset, true, false, false);

		XYPlot plot = result.getXYPlot();
		plot.getDomainAxis().setAutoRange(true);
		plot.getRangeAxis().setAutoRange(true);

		NumberAxis na = (NumberAxis) plot.getRangeAxis();
		NumberFormat nf = new DecimalFormat("0.00000");
		na.setNumberFormatOverride(nf);

		return result;
	}

	// === get/set === //
	public ChartManager getChartManager() {
		return chartManager;
	}

	protected DataManager getDataManager() {
		return dataManager;
	}

	protected int getChartSize() {
		return chartSize;
	}

	protected void setChartSize(int chartSize) {
		this.chartSize = chartSize;
	}

	protected int getHistorySize() {
		return historySize;
	}

	protected Map<String, DynamicTimeSeriesCollection> getDatasets() {
		return datasets;
	}

	protected void setDataManager(DataManager dataManager) {
		this.dataManager = dataManager;
	}

	protected void setChartManager(ChartManager chartManager) {
		this.chartManager = chartManager;
	}

	protected void setHistorySize(int historySize) {
		this.historySize = historySize;
	}
}
